package com.wjk.kylin.mall.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wjk.kylin.id.core.uid.UidGenerator;
import com.wjk.kylin.lock.annotation.KylinLock;
import com.wjk.kylin.mall.common.core.dto.base.BaseOutDTO;
import com.wjk.kylin.mall.common.core.dto.base.DataIdInDTO;
import com.wjk.kylin.mall.common.core.dto.base.DataOutDTO;
import com.wjk.kylin.mall.common.core.dto.base.DataPageInDTO;
import com.wjk.kylin.mall.common.core.bo.base.PageBO;
import com.wjk.kylin.mall.common.redis.component.BusinessNoGenerator;
import com.wjk.kylin.mall.common.redis.component.BusinessTypeEnum;
import com.wjk.kylin.mall.common.web.stream.StreamQueryHandler;
import com.wjk.kylin.mall.common.web.transactional.TransactionalHandle;
import com.wjk.kylin.mall.order.beanmapper.OrderEntityMapper;
import com.wjk.kylin.mall.order.bo.OrderBO;
import com.wjk.kylin.mall.order.dto.OrderAddInDTO;
import com.wjk.kylin.mall.order.dto.OrderUpdateInDTO;
import com.wjk.kylin.mall.order.entity.OrderEntity;
import com.wjk.kylin.mall.order.mapper.OrderMapper;
import com.wjk.kylin.mall.order.service.IOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;


/**
 * 订单
 */
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderEntity> implements IOrderService {
    @Autowired
    @Qualifier("cachedUidGenerator")
    private UidGenerator uidGenerator;
    @Autowired
    private TransactionalHandle transactionalHandle;
    @Autowired
    private BusinessNoGenerator businessNoGenerator;

    @Override
    @Transactional
    public BaseOutDTO updateById(OrderUpdateInDTO inDTO) {
        OrderEntity entity = OrderEntityMapper.INSTANCE.updateDto2Entity(inDTO);
        entity.setUpdateTime(new Date());

        if (super.updateById(entity)) {
            return BaseOutDTO.success();
        }
        return BaseOutDTO.error("更新数据失败");
    }

    /**
     * 新增
     *
     * @param inDTO
     * @return
     */
    @Override
    @KylinLock(keys = "#inDTO.memberId")
    @Transactional
    public BaseOutDTO add(OrderAddInDTO inDTO) {
        OrderEntity entity = OrderEntityMapper.INSTANCE.addDto2Entity(inDTO);

        entity.setCreateTime(new Date());
        entity.setUpdateTime(new Date());
        //工具类 生成有规则的订单号
        entity.setOrderNumber(businessNoGenerator.generate(BusinessTypeEnum.ORDER));
        entity.setId(uidGenerator.getUID());

        //执行事务
        boolean flag = transactionalHandle.execute(() -> addEntity(entity));
        log.info("OrderServiceImpl-add,flag:{}", flag);
        if (flag) {
            return BaseOutDTO.success();
        }
        return BaseOutDTO.error("操作失败，请重试！");
    }

    /**
     * 查询
     *
     * @param inDTO
     * @return
     */
    @Override
    public BaseOutDTO get(DataIdInDTO inDTO) {
        DataOutDTO<OrderBO> dataOutDTO = new DataOutDTO<>();

        OrderEntity orderEntity = super.getById(inDTO.getId());
        dataOutDTO.setData(OrderEntityMapper.INSTANCE.entity2BO(orderEntity));

        return dataOutDTO;
    }

    /**
     * 分页查询数据
     *
     * @param inDTO
     * @return
     */
    @Override
    public BaseOutDTO page(DataPageInDTO inDTO) {
        DataOutDTO<PageBO> outDTO = new DataOutDTO<>();

        Page<OrderEntity> page = super.page(new Page<>(inDTO.getPageNum(), inDTO.getPageSize()), new QueryWrapper<OrderEntity>().orderByAsc("id"));

        outDTO.setData(new PageBO(OrderEntityMapper.INSTANCE.entity2BOs(page.getRecords()), page.getTotal(), page.getSize(), page.getCurrent()));

        return outDTO;
    }

    /**
     * 流式查询
     *
     * @return
     */
    @Override
    public BaseOutDTO stream() {
        OrderEntity entity = new OrderEntity();
        entity.setId(2459L);

        StreamQueryHandler<OrderEntity> stream = new StreamQueryHandler<>();
        stream.batchHandle(baseMapper::streamDataDynamicHandle, this::handle);
        stream.batchHandle(baseMapper::streamDataDynamicHandle, (v) -> handle(entity, v));
        stream.batchHandle((v) -> baseMapper.streamDataDynamicHandle(entity, v), this::handle);
        stream.batchHandle((v) -> baseMapper.streamDataDynamicHandle(entity, v), (v) -> handle(entity, v));

        return BaseOutDTO.success();
    }

    /**
     * 流式查询 处理查询结果
     *
     * @param list
     */
    public void handle(OrderEntity orderEntity, List<OrderEntity> list) {
        System.out.println("handle_2_" + list.size());
        System.out.println("handle_2_orderEntity:" + orderEntity);
//        for (OrderEntity entity : list) {
//            System.out.println(entity);
//        }
    }

    /**
     * 流式查询 处理查询结果
     *
     * @param list
     */
    public void handle(List<OrderEntity> list) {
        System.out.println("handle_1_" + list.size());
//        for (OrderEntity item : list) {
//            System.out.println(item);
//        }
    }

    /**
     * 执行事务的方法
     */
    public boolean addEntity(OrderEntity entity) {
        return super.save(entity);
    }

}
